home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 68K / Mac / Demo / sound / morse.py next >
Text File  |  1996-05-20  |  4KB  |  181 lines

  1. import sys, math, audiodev
  2.  
  3. DOT = 30
  4. DAH = 80
  5. OCTAVE = 2                # 1 == 441 Hz, 2 == 882 Hz, ...
  6. SAMPWIDTH = 2
  7. FRAMERATE = 44100
  8. BASEFREQ = 441
  9. QSIZE = 20000
  10.  
  11. morsetab = {
  12.     'A': '.-',        'a': '.-',
  13.     'B': '-...',        'b': '-...',
  14.     'C': '-.-.',        'c': '-.-.',
  15.     'D': '-..',        'd': '-..',
  16.     'E': '.',        'e': '.',
  17.     'F': '..-.',        'f': '..-.',
  18.     'G': '--.',        'g': '--.',
  19.     'H': '....',        'h': '....',
  20.     'I': '..',        'i': '..',
  21.     'J': '.---',        'j': '.---',
  22.     'K': '-.-',        'k': '-.-',
  23.     'L': '.-..',        'l': '.-..',
  24.     'M': '--',        'm': '--',
  25.     'N': '-.',        'n': '-.',
  26.     'O': '---',        'o': '---',
  27.     'P': '.--.',        'p': '.--.',
  28.     'Q': '--.-',        'q': '--.-',
  29.     'R': '.-.',        'r': '.-.',
  30.     'S': '...',        's': '...',
  31.     'T': '-',        't': '-',
  32.     'U': '..-',        'u': '..-',
  33.     'V': '...-',        'v': '...-',
  34.     'W': '.--',        'w': '.--',
  35.     'X': '-..-',        'x': '-..-',
  36.     'Y': '-.--',        'y': '-.--',
  37.     'Z': '--..',        'z': '--..',
  38.     '0': '-----',
  39.     '1': '.----',
  40.     '2': '..---',
  41.     '3': '...--',
  42.     '4': '....-',
  43.     '5': '.....',
  44.     '6': '-....',
  45.     '7': '--...',
  46.     '8': '---..',
  47.     '9': '----.',
  48.     ',': '--..--',
  49.     '.': '.-.-.-',
  50.     '?': '..--..',
  51.     ';': '-.-.-.',
  52.     ':': '---...',
  53.     "'": '.----.',
  54.     '-': '-....-',
  55.     '/': '-..-.',
  56.     '(': '-.--.-',
  57.     ')': '-.--.-',
  58.     '_': '..--.-',
  59.     ' ': ' '
  60. }
  61.  
  62. # If we play at 44.1 kHz (which we do), then if we produce one sine
  63. # wave in 100 samples, we get a tone of 441 Hz.  If we produce two
  64. # sine waves in these 100 samples, we get a tone of 882 Hz.  882 Hz
  65. # appears to be a nice one for playing morse code.
  66. def mkwave(octave):
  67.     global sinewave, nowave
  68.     sinewave = ''
  69.     n = int(FRAMERATE / BASEFREQ)
  70.     for i in range(n):
  71.         val = int(math.sin(2 * math.pi * i * octave / n) * 0x7fff)
  72.         sample = chr((val >> 8) & 255) + chr(val & 255)
  73.         sinewave = sinewave + sample[:SAMPWIDTH]
  74.     nowave = '\0' * (n*SAMPWIDTH)
  75.  
  76. mkwave(OCTAVE)
  77.  
  78. class BufferedAudioDev:
  79.     def __init__(self, *args):
  80.         import audiodev
  81.         self._base = apply(audiodev.AudioDev, args)
  82.         self._buffer = []
  83.         self._filled = 0
  84.         self._addmethods(self._base, self._base.__class__)
  85.     def _addmethods(self, inst, cls):
  86.         for name in cls.__dict__.keys():
  87.             if not hasattr(self, name):
  88.                 try:
  89.                     setattr(self, name, getattr(inst, name))
  90.                 except:
  91.                     pass
  92.         for basecls in cls.__bases__:
  93.             self._addmethods(self, inst, basecls)
  94.     def writeframesraw(self, frames):
  95.         self._buffer.append(frames)
  96.         self._filled = self._filled + len(frames)
  97.         if self._filled >= QSIZE:
  98.             self.flush()
  99.     def wait(self):
  100.         self.flush()
  101.         self._base.wait()
  102.     def flush(self):
  103.         print 'flush: %d blocks, %d bytes' % (len(self._buffer), self._filled)
  104.         if self._buffer:
  105.             import string
  106.             self._base.writeframes(string.joinfields(self._buffer, ''))
  107.             self._buffer = []
  108.             self._filled = 0
  109.  
  110. def main(args = sys.argv[1:]):
  111.     import getopt, string
  112.     try:
  113.         opts, args = getopt.getopt(args, 'o:p:')
  114.     except getopt.error:
  115.         sys.stderr.write('Usage ' + sys.argv[0] +
  116.                  ' [ -o outfile ] [ args ] ...\n')
  117.         sys.exit(1)
  118.     dev = None
  119.     for o, a in opts:
  120.         if o == '-o':
  121.             import aifc
  122.             dev = aifc.open(a, 'w')
  123.             dev.setframerate(FRAMERATE)
  124.             dev.setsampwidth(SAMPWIDTH)
  125.             dev.setnchannels(1)
  126.         if o == '-p':
  127.             mkwave(string.atoi(a))
  128.     if not dev:
  129.         dev = BufferedAudioDev()
  130.         dev.setoutrate(FRAMERATE)
  131.         dev.setsampwidth(SAMPWIDTH)
  132.         dev.setnchannels(1)
  133.         dev.close = dev.stop
  134.     if args:
  135.         line = string.join(args)
  136.     else:
  137.         line = sys.stdin.readline()
  138.     while line:
  139.         print line
  140.         mline = morse(line)
  141.         print mline
  142.         play(mline, dev)
  143.         if hasattr(dev, 'wait'):
  144.             dev.wait()
  145.         if not args:
  146.             line = sys.stdin.readline()
  147.         else:
  148.             line = ''
  149.     dev.close()
  150.  
  151. # Convert a string to morse code with \001 between the characters in
  152. # the string.
  153. def morse(line):
  154.     res = ''
  155.     for c in line:
  156.         try:
  157.             res = res + morsetab[c] + '\001'
  158.         except KeyError:
  159.             pass
  160.     return res
  161.  
  162. # Play a line of morse code.
  163. def play(line, dev):
  164.     for c in line:
  165.         if c == '.':
  166.             sine(dev, DOT)
  167.         elif c == '-':
  168.             sine(dev, DAH)
  169.         else:
  170.             pause(dev, DAH)
  171.         pause(dev, DOT)
  172.  
  173. def sine(dev, length):
  174.     dev.writeframesraw(sinewave*length)
  175.  
  176. def pause(dev, length):
  177.     dev.writeframesraw(nowave*length)
  178.  
  179. if __name__ == '__main__' or sys.argv[0] == __name__:
  180.     main()
  181.